package core.proto.timeline;

import static app.constants.CollabVizConstants.*;
import java.awt.Dimension;
import java.awt.FlowLayout;

import javax.swing.JPanel;
import javax.swing.JSlider;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;

import core.proto.Util;

import de.jaret.util.ui.timebars.swing.TimeBarViewer;


/**
 * Class based on the de.jaret.examples.timebars.eventmonitoring.swing.EventMonitoringControlPanel. 
 * 
 * Purpose: as a control (in the mvc model), which displays the scale bar for the TimeBarViewer. 
 * @author Wei 
 *
 */
public class ScaleControlPanel extends JPanel {
	private static final long serialVersionUID = 1L;

	TimeBarViewer _viewer;
	JSlider _timeScaleSlider;

	public ScaleControlPanel(TimeBarViewer viewer, int initalSecondsDisplayed, int height) {
		_viewer = viewer;
		this.setPreferredSize(new Dimension(Util.getTimelineWidth(), height));
		setLayout(new FlowLayout());
		createControls(initalSecondsDisplayed);
	}

	/**
	 * Purpose: initializes the slider and ties it to the zooming of the timeline.
	 * @param initialSeconds How many seconds are displayed initially in the view. 
	 */
	private void createControls(int initialSeconds) {
		 final double minSecondsDisplayed = SECONDS_IN_A_DAY;
//		 final double maxSecondsDisplayed = 3 * 365 * 24 * 60 * 60; // max nummber of seconds displayed (3 years in seconds)
		 final double maxSecondsDisplayed = _viewer.getMaxDate().diffSeconds(_viewer.getMinDate());
		 final double slidermax = 1000; // slider maximum (does not really matter)
		 
		 _timeScaleSlider = new JSlider(0, (int) slidermax);

		 final int fudge = 100;
		 _timeScaleSlider.setPreferredSize(
				 new Dimension(
						 _timeScaleSlider.getPreferredSize().width * 4 - fudge, _timeScaleSlider
				 .getPreferredSize().height));
		 add(_timeScaleSlider);

		 // I don't really get what these do but they make the timebar work so I leave them be. 
		 final double b = 1.0 / 100.0; // additional factor to reduce the absolut values in the exponent
		 final double faktor = (minSecondsDisplayed - maxSecondsDisplayed) / (1 - Math.pow(2, slidermax * b)); // factor for the exp function
		 final double c = (minSecondsDisplayed - faktor);

		 int initialSliderVal = calcInitialSliderVal(c, b, faktor, initialSeconds);
		 _timeScaleSlider.setValue((int) (slidermax- initialSliderVal));

		 _timeScaleSlider.addChangeListener(new ChangeListener() {
			 public void stateChanged(ChangeEvent e) {
				 final double x = slidermax - (double) _timeScaleSlider.getValue(); // reverse x
				 double seconds = c + faktor * Math.pow(2, x * b); // calculate the seconds to display
				 _viewer.setSecondsDisplayed((int) seconds, true);
			 }
		 });
	 }

	 private int calcInitialSliderVal(double c, double b, double faktor, int seconds) {

		 double x = 1 / b * log2((seconds - c) / faktor);

		 return (int) x;
	 }

	 private double log2(double a) {
		 return Math.log(a) / Math.log(2);
	 }

}